﻿using Bot.Infrastructure;
using Bot.Domain;
using Google.Cloud.Dialogflow.V2;
using Google.LongRunning;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;


namespace Bot.Domain.DialogFlow
{
    public interface IDialogFlowService : IHttpWebRequestMethod
    {
        Task<Agent> getAgentAsync(string key, string projectId);
        Task<Operation> agentExportAsync(string key, string projectId);
        Task<Operation> agentImportAsync(string key, string projectId, string agentContent);
        Task<Operation> agentRestoreAsync(string key, string projectId, string agentContent);
        Task<SearchAgents> agentSearchAsync(string key, string projectId, string pageToken);
        Task<Operation> agentTrainAsync(string key, string projectId);

        Task<Operation> entityTypesEntitiesBatchCreateAsync(string key, string projectId, string json);
        Task<Operation> entityTypesEntitiesBatchDeleteAsync(string key, string projectId, string json);
        Task<Operation> entityTypesEntitiesBatchUpdateAsync(string projectId);

        Task<Operation> agentEntityTypesBatchDeleteAsync(string key, string projectId, string[] entityNameArray);
        Task<Operation> agentEntityTypesBatchUpdateAsync(string projectId);
        Task<EntityType> agentEntityTypesCreateAsync(string projectId);
        Task<string> agentEntityTypesDeleteAsync(string projectId);
        Task<EntityType> agentEntityTypesGetAsync(string projectId);
        Task<SearchEntities> agentEntityTypesListAsync(string key, string projectId, string pageToken);
        Task<EntityType> agentEntityTypesPatchAsync(string projectId);

        Task<Operation> projectsOperationsGet(string key, string operationName);
        //intent
        Task<Google.Cloud.Dialogflow.V2.Intent> CreateIntent(string key, string projectId, Google.Cloud.Dialogflow.V2.Intent intent, string languageCode);
        Task DeleteIntent(string key, string projectId, string intentId);
        Task<Google.Cloud.Dialogflow.V2.Intent> EditIntent(string key, string projectId, string intentId, Google.Cloud.Dialogflow.V2.Intent intent, string languageCode);
        Task<Google.Cloud.Dialogflow.V2.Intent> GetIntent(string key, string projectId, string intentId);
        Task<SearchIntents> GetIntentList(string key, string projectId, int pageSize, string pageToken);
        Task<Operation> BatchDeleteIntents(string key, string projectId, string[] intentNames);
        Task<Operation> BatchUpdateIntents(string key, string projectId, Google.Cloud.Dialogflow.V2.Intent[] intent);
        //detectintent
        //DetectIntentRequest

        //entity
        Task<EntityType> CreateEntity(string key, string projectId, EntityType entitytype, string languageCode);
        Task DeleteEntity(string key, string projectId, string entitytypeid);
        Task<EntityType> EditEntity(string key, string projectId, string entitytypeid, EntityType entitytype, string languageCode);

        Task<DetectIntentResponseForDialogFlow> DetectIntentAsync(string key, string projectId, string sessionId, DetectIntentRequest request);
        Task DeleteContext(string key, string contextName);
        Task<Operation> BatchUpdateEntities(string key, string projectId, EntityType[] entities);
    }
    public class DialogFlowService : HttpWebRequestMethod, IDialogFlowService
    {
        private bool Debug { get; } = false;
        public DialogFlowService()
        {
#if DEBUG
            Debug = true;
#endif
        }

        public async Task<DetectIntentResponseForDialogFlow> DetectIntentAsync(string key, string projectId, string sessionId, DetectIntentRequest request)
        {
            //POST https://dialogflow.googleapis.com/v2/{session=projects/*/agent/sessions/*}:detectIntent
            DetectIntentResponseForDialogFlow response = new DetectIntentResponseForDialogFlow();
#if DEBUG
            StringBuilder sb = new StringBuilder();
            sb.Append("{");
            sb.Append("\"responseId\": \"111111111111111111111111111\",");
            sb.Append("\"queryResult\": {");
            sb.Append("\"queryText\": \"你好\",");
            sb.Append("\"parameters\": { ");
            sb.Append("\"mytest\": \"aaaa\",");
            sb.Append("\"w2\": \"w2222\",");
            sb.Append("\"w4\": \"w4444\"");
            sb.Append("},");
            sb.Append("\"allRequiredParamsPresent\": false,");
            sb.Append("\"fulfillmentText\": \"how are you\",");
            sb.Append("\"fulfillmentMessages\": [");
            sb.Append(" {");
            sb.Append(" \"text\": {");
            sb.Append("  \"test\": [");
            sb.Append("      \"how are you\"");
            sb.Append("   ]");
            sb.Append("}");
            sb.Append("}");
            sb.Append("],");
            sb.Append("\"intent\": {");
            sb.Append("\"name\": \"projects/regal-sled-204110/agent/intents/a50854bd-b32e-4d52-bf66-538f9ac75059\",");
            sb.Append(" \"displayName\": \"fs\"");
            sb.Append("},");
            sb.Append("\"intentDetectionConfidence\": 0.9,");
            sb.Append(" \"languageCode\": \"en\"");
            sb.Append("}");
            sb.Append("}");
            response = JsonConvert.DeserializeObject<DetectIntentResponseForDialogFlow>(sb.ToString());
            return response;
#endif 
            string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent/sessions/{1}:detectIntent";
            uriString = string.Format(uriString, projectId, sessionId);
            DetectIntentContentDto detectRequest = IntentContentConvertor.FromDialogflow(request);
            string json = JsonConvert.SerializeObject(detectRequest);
            //LogHelper.Debug(json);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
                Content = new StringContent(json, Encoding.UTF8, "application/json")
            };
            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key, 120);
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            //LogHelper.Debug(strResult);
            if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
            {
                return JsonConvert.DeserializeObject<DetectIntentResponseForDialogFlow>(strResult);
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        public async Task DeleteContext(string key,string contextName)
        {
#if DEBUG
            return;
#endif 
            //delete
            string uriString = "https://dialogflow.googleapis.com/v2/{0}";
            uriString = string.Format(uriString, contextName);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
            };
            HttpResponseMessage httpResponseMessage = await DeleteAsync(httpRequestMessage, key, 120);
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
            {
                return;
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        public async Task<Agent> getAgentAsync(string key, string projectId)
        {
            if (Debug)
            {
                string json = Utils.GetResourceContent(this.GetType(), "DialogFlow.Json.projects_getAgent.json").Substring(1);

                return JsonConvert.DeserializeObject<Agent>(json, new MatchModeStringEnumConverter());
            }
            else
            {
                //GET https://dialogflow.googleapis.com/v2/{parent=projects/*}/agent
                Agent agent = new Agent();
                string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent";
                uriString = string.Format(uriString, projectId);
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString)
                };
                HttpResponseMessage httpResponseMessage = await GetAsync(httpRequestMessage, key);
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                    agent = JsonConvert.DeserializeObject<Agent>(strResult, new MatchModeStringEnumConverter());
                }
                return agent;
            }
        }
        public async Task<Operation> agentExportAsync(string key, string projectId)
        {
            if (Debug)
            {
                return new Operation
                {
                    Name = "projects/test-469dc/operations/8ee63be0-9b5f-4e23-ab5c-67ae6caa5897",
                    Done = true,
                    Response = new Google.Protobuf.WellKnownTypes.Any
                    {
                        TypeUrl = "type.googleapis.com/google.cloud.diaflow.v2.ExportAgentResponse",
                        Value = Google.Protobuf.ByteString.FromBase64("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")
                    }
                };
            }
            else
            {
                //POST https://dialogflow.googleapis.com/v2/{parent=projects/*}/agent:export
                Operation operation = new Operation();
                string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent:export";
                uriString = string.Format(uriString, projectId);
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString)
                };
                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    string strResult = await httpResponseMessage.Content.ReadAsStringAsync();

                    operation = JsonConvert.DeserializeObject<Operation>(strResult);

                }
                return operation;
            }
        }
        public async Task<Operation> agentImportAsync(string key, string projectId, string agentContent)
        {
            if (Debug)
            {
                return new Operation
                {
                    Done = true,
                };
            }
            else
            {
                //POST https://dialogflow.googleapis.com/v2/{parent=projects/*}/agent:import
                Operation operation = new Operation();
                string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent:import";
                uriString = string.Format(uriString, projectId);
                string json = JsonConvert.SerializeObject(new { agentContent });
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                    Content = new StringContent(json, Encoding.UTF8, "application/json")
                };

                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key, 120);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                operation = JsonConvert.DeserializeObject<Operation>(strResult);
                return operation;
            }
        }
        public async Task<Operation> agentRestoreAsync(string key, string projectId, string agentContent)
        {
            if (Debug)
            {
                return new Operation
                {
                    Done = true,
                };
            }
            else
            {
                //POST https://dialogflow.googleapis.com/v2/{parent=projects/*}/agent:restore
                Operation operation = new Operation();
                string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent:restore";
                uriString = string.Format(uriString, projectId);
                string json = JsonConvert.SerializeObject(new { agentContent });
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                    Content = new StringContent(json, Encoding.UTF8, "application/json")
                };

                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key, 120);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                operation = JsonConvert.DeserializeObject<Operation>(strResult);
                return operation;
            }
        }
        public async Task<SearchAgents> agentSearchAsync(string key, string projectId, string pageToken)
        {
            //GET https://dialogflow.googleapis.com/v2/{parent=projects/*}/agent:search
            SearchAgents searchAgents = new SearchAgents();
            string uriString = "";
            if (!string.IsNullOrEmpty(pageToken))
            {
                uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent:search?pageSize=500pageToken={1}";
                uriString = string.Format(uriString, projectId, pageToken);
            }
            else
            {
                uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent:search?pageSize=500";
                uriString = string.Format(uriString, projectId);
            }

            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString)
            };
            HttpResponseMessage httpResponseMessage = await GetAsync(httpRequestMessage, key);
            if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
            {
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                searchAgents = JsonConvert.DeserializeObject<SearchAgents>(strResult, new MatchModeStringEnumConverter());
            }
            return searchAgents;
        }
        public async Task<Operation> agentTrainAsync(string key, string projectId)
        {
            if (Debug)
            {
                return new Operation
                {
                    Done = true,
                    Name = string.Format("projects/{0}/operation/{1}", projectId, Guid.NewGuid().ToString())
                };
            }
            else
            {
                //POST https://dialogflow.googleapis.com/v2/{parent=projects/*}/agent:train
                Operation operation = new Operation();
                string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent:train";
                uriString = string.Format(uriString, projectId);
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString)
                };
                var settings = new JsonSerializerSettings
                {
                    ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
                    NullValueHandling = NullValueHandling.Ignore
                };
                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key, 120);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    return JsonConvert.DeserializeObject<Operation>(strResult, settings);
                }
                Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
                throw new ExceptionWithCode(50044, error.Error.Message);
            }
        }
        #region Entity
        public async Task<Operation> entityTypesEntitiesBatchCreateAsync(string key, string projectId, string json)
        {
            //POST https://dialogflow.googleapis.com/v2/{parent=projects/*/agent/entityTypes/*}/entities:batchCreate
            Operation operation = new Operation();
            string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent:train";
            uriString = string.Format(uriString, projectId);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
                Content = new StringContent(json, Encoding.UTF8, "application/json")
            };

            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            operation = JsonConvert.DeserializeObject<Operation>(strResult);
            return operation;
        }

        public async Task<Operation> entityTypesEntitiesBatchDeleteAsync(string key, string projectId, string json)
        {
            //POST https://dialogflow.googleapis.com/v2/{parent=projects/*/agent/entityTypes/*}/entities:batchDelete
            Operation operation = new Operation();
            string uriString = "https://dialogflow.googleapis.com/v2/projects/*/agent/entityTypes/*}/entities:batchDelete";
            uriString = string.Format(uriString, projectId);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
                Content = new StringContent(json, Encoding.UTF8, "application/json")
            };

            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            operation = JsonConvert.DeserializeObject<Operation>(strResult);
            return operation;
        }
        public async Task<Operation> entityTypesEntitiesBatchUpdateAsync(string projectId)
        {
            //POST https://dialogflow.googleapis.com/v2/{parent=projects/*/agent/entityTypes/*}/entities:batchUpdate
            Operation operation = new Operation();
            return operation;
        }

        public async Task<Operation> agentEntityTypesBatchDeleteAsync(string key, string projectId, string[] entityNameArray)
        {
            if (Debug)
            {
                string json = Utils.GetResourceContent(this.GetType(), "DialogFlow.Json.projects_agent_entities_batchDelete.json").Substring(1);

                return JsonConvert.DeserializeObject<Operation>(json, new MatchModeStringEnumConverter());
            }
            else
            {
                //POST https://dialogflow.googleapis.com/v2/{parent=projects/*/agent}/entityTypes:batchDelete
                Operation operation = new Operation();
                string uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent/entityTypes:batchDelete";
                uriString = string.Format(uriString, projectId);
                string json = JsonConvert.SerializeObject(new { entityTypeNames = entityNameArray });
                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                    Content = new StringContent(json, Encoding.UTF8, "application/json")
                };
                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                operation = JsonConvert.DeserializeObject<Operation>(strResult);
                return operation;
            }
        }
        public async Task<Operation> agentEntityTypesBatchUpdateAsync(string projectId)
        {
            //POST https://dialogflow.googleapis.com/v2/{parent=projects/*/agent}/entityTypes:batchUpdate
            Operation operation = new Operation();
            return operation;
        }
        public async Task<EntityType> agentEntityTypesCreateAsync(string projectId)
        {
            //POST https://dialogflow.googleapis.com/v2/{parent=projects/*/agent}/entityTypes
            EntityType entityType = new EntityType();
            return entityType;
        }
        public async Task<string> agentEntityTypesDeleteAsync(string projectId)
        {
            //DELETE https://dialogflow.googleapis.com/v2/{name=projects/*/agent/entityTypes/*}
            string strResult = "";
            return strResult;
        }
        public async Task<EntityType> agentEntityTypesGetAsync(string projectId)
        {
            //GET https://dialogflow.googleapis.com/v2/{name=projects/*/agent/entityTypes/*}
            EntityType entityType = new EntityType();
            return entityType;
        }
        public async Task<SearchEntities> agentEntityTypesListAsync(string key, string projectId, string pageToken)
        {
            if (Debug)
            {
                string json = Utils.GetResourceContent(this.GetType(), "DialogFlow.Json.projects_agent_entityTypes_list.json").Substring(1);

                return JsonConvert.DeserializeObject<SearchEntities>(json, new MatchModeStringEnumConverter());
            }
            else
            {
                //GET https://dialogflow.googleapis.com/v2/{parent=projects/*/agent}/entityTypes
                SearchEntities searchEntities = new SearchEntities();
                string uriString = "";
                if (!string.IsNullOrEmpty(pageToken))
                {
                    uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent/entityTypes?pageSize=500pageToken={1}";
                    uriString = string.Format(uriString, projectId, pageToken);
                }
                else
                {
                    uriString = "https://dialogflow.googleapis.com/v2/projects/{0}/agent/entityTypes?pageSize=500";
                    uriString = string.Format(uriString, projectId);
                }

                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString)
                };
                HttpResponseMessage httpResponseMessage = await GetAsync(httpRequestMessage, key);
                if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                    searchEntities = JsonConvert.DeserializeObject<SearchEntities>(strResult, new MatchModeStringEnumConverter());
                }
                return searchEntities;
            }
        }
        public async Task<EntityType> agentEntityTypesPatchAsync(string projectId)
        {
            //PATCH https://dialogflow.googleapis.com/v2/{entityType.name=projects/*/agent/entityTypes/*}
            EntityType entityType = new EntityType();
            return entityType;
        }
        #endregion
        #region Entity
        public async Task<EntityType> CreateEntity(string key, string projectId, EntityType entitytype, string languageCode)
        {
#if DEBUG
            EntityType debugResult = new EntityType();
            debugResult.DisplayName = entitytype.DisplayName;
            debugResult.Name = string.Format("projects/{0}/agent/entityTypes/{1}", projectId, Guid.NewGuid().ToString());
            return debugResult;
#endif
            PropertyIgnoreSerializerContractResolver jsonResolver = new PropertyIgnoreSerializerContractResolver();
            jsonResolver.IgnoreProperty(typeof(Google.Cloud.Dialogflow.V2.Intent), "intentName");
            jsonResolver.IgnoreProperty(typeof(EntityType), "entityTypeName");

            var settings = new JsonSerializerSettings
            {
                ContractResolver = jsonResolver,
                NullValueHandling = NullValueHandling.Ignore
            };
            string uristring = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/entityTypes?languageCode={1}", projectId, languageCode);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uristring),
                Content = new StringContent(JsonConvert.SerializeObject(entitytype, settings), Encoding.UTF8, "application/json")
            };
            //LogHelper.Debugf("create Entity: {0}", JsonConvert.SerializeObject(entitytype, settings));
            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
            //httpResponseMessage.EnsureSuccessStatusCode();
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return JsonConvert.DeserializeObject<EntityType>(strResult, new MatchModeStringEnumConverter());
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        public async Task DeleteEntity(string key, string projectId, string entitytypeid)
        {
#if DEBUG            
            return;
#endif
            string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/entityTypes/{1}", projectId, entitytypeid);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString)
            };

            HttpResponseMessage httpResponseMessage = await DeleteAsync(httpRequestMessage, key);
            if (httpResponseMessage.IsSuccessStatusCode) return;
            if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                return;
            }
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        public async Task<EntityType> EditEntity(string key, string projectId, string entitytypeid, EntityType entitytype, string languageCode)
        {
#if DEBUG
            EntityType debugResult = new EntityType();
            debugResult.DisplayName = entitytype.DisplayName;
            debugResult.Name = string.Format("projects/{0}/agent/entityTypes/{1}", projectId, Guid.NewGuid().ToString());
            return debugResult;
#endif
            PropertyIgnoreSerializerContractResolver jsonResolver = new PropertyIgnoreSerializerContractResolver();
            jsonResolver.IgnoreProperty(typeof(Google.Cloud.Dialogflow.V2.Intent), "intentName");
            jsonResolver.IgnoreProperty(typeof(EntityType), "entityTypeName");

            var settings = new JsonSerializerSettings
            {
                ContractResolver = jsonResolver,
                NullValueHandling = NullValueHandling.Ignore
            };
            string uristring = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/entityTypes/{1}?languageCode={2}", projectId, entitytypeid, languageCode);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uristring),
                Method = HttpMethod.Post,
                Content = new StringContent(JsonConvert.SerializeObject(entitytype, settings), Encoding.UTF8, "application/json")
            };
            httpRequestMessage.Headers.Add("x-http-method-override", "PATCH");
            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return JsonConvert.DeserializeObject<EntityType>(strResult, new MatchModeStringEnumConverter());
            }
            if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.NotFound)
            {//if not found,create
                entitytype.Name = "";
                return await CreateEntity(key, projectId, entitytype, languageCode);
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }


        #endregion
        public async Task<Operation> projectsOperationsGet(string key, string operationName)
        {
            //GET https://dialogflow.googleapis.com/v2/{name=projects/*/operations/*}
            Operation operation = new Operation();
#if DEBUG
            operation.Error = null;
            operation.Done = true;
            return operation;
#endif
            string uriString = "https://dialogflow.googleapis.com/v2/{0}";
            uriString = string.Format(uriString, operationName);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString)
            };
            HttpResponseMessage httpResponseMessage = await GetAsync(httpRequestMessage, key);
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            operation = JsonConvert.DeserializeObject<Operation>(strResult, new MatchModeStringEnumConverter());
            return operation;
        }
        #region Intent
        public async Task<Google.Cloud.Dialogflow.V2.Intent> CreateIntent(string key, string projectId, Google.Cloud.Dialogflow.V2.Intent intent, string languageCode)
        {
#if DEBUG
            Google.Cloud.Dialogflow.V2.Intent debugResult = new Google.Cloud.Dialogflow.V2.Intent();
            debugResult.DisplayName = intent.DisplayName;
            debugResult.Name = string.Format("projects/{0}/agent/intents/{1}", projectId, Guid.NewGuid().ToString());
            return debugResult;
#endif
            PropertyIgnoreSerializerContractResolver jsonResolver = new PropertyIgnoreSerializerContractResolver();
            jsonResolver.IgnoreProperty(typeof(Google.Cloud.Dialogflow.V2.Intent), "intentName");
            jsonResolver.IgnoreProperty(typeof(EntityType), "entityTypeName");

            var settings = new JsonSerializerSettings
            {
                ContractResolver = jsonResolver,
                NullValueHandling = NullValueHandling.Ignore
            };
            string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/intents?languageCode={1}", projectId, languageCode);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
                Content = new StringContent(JsonConvert.SerializeObject(intent, settings), Encoding.UTF8, "application/json")
            };
            //LogHelper.Debugf("create intent: {0}", JsonConvert.SerializeObject(intent, settings));
            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key, 180);
            //httpResponseMessage.EnsureSuccessStatusCode();           

            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return JsonConvert.DeserializeObject<Google.Cloud.Dialogflow.V2.Intent>(strResult, settings);
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);

            //if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.OK)
            //{
            //    string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            //    operation = JsonConvert.DeserializeObject<Operation>(strResult, new MatchModeStringEnumConverter());
            //}
        }
        public async Task DeleteIntent(string key, string projectId, string intentId)
        {
#if DEBUG
            return;
#endif
            string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/intents/{1}", projectId, intentId);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString)
            };
            HttpResponseMessage httpResponseMessage = await DeleteAsync(httpRequestMessage, key);
            if (httpResponseMessage.IsSuccessStatusCode) return;
            if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                return;
            }
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        public async Task<Google.Cloud.Dialogflow.V2.Intent> EditIntent(string key, string projectId, string intentId, Google.Cloud.Dialogflow.V2.Intent intent, string languageCode)
        {
#if DEBUG
            Google.Cloud.Dialogflow.V2.Intent debugResult = new Google.Cloud.Dialogflow.V2.Intent();
            debugResult.DisplayName = intent.DisplayName;
            debugResult.Name = string.Format("projects/{0}/agent/intents/{1}", projectId, Guid.NewGuid().ToString());
            return debugResult;
#endif
            PropertyIgnoreSerializerContractResolver jsonResolver = new PropertyIgnoreSerializerContractResolver();
            jsonResolver.IgnoreProperty(typeof(Google.Cloud.Dialogflow.V2.Intent), "intentName");
            jsonResolver.IgnoreProperty(typeof(EntityType), "entityTypeName");

            var settings = new JsonSerializerSettings
            {
                ContractResolver = jsonResolver,
                NullValueHandling = NullValueHandling.Ignore
            };
            string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/intents/{1}?languageCode={2}", projectId, intentId, languageCode);
            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
                Method = HttpMethod.Post,
                Content = new StringContent(JsonConvert.SerializeObject(intent, settings), Encoding.UTF8, "application/json"),
            };
            httpRequestMessage.Headers.Add("x-http-method-override", "PATCH");

            //LogHelper.Debugf("edit intent: {0}", JsonConvert.SerializeObject(intent, settings));

            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return JsonConvert.DeserializeObject<Google.Cloud.Dialogflow.V2.Intent>(strResult, settings);
            }
            if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.NotFound)
            {//if not found,create
                intent.Name = "";
                return await CreateIntent(key, projectId, intent, languageCode);
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        public async Task<Google.Cloud.Dialogflow.V2.Intent> GetIntent(string key, string projectId, string intentId)
        {
            var settings = new JsonSerializerSettings
            {
                ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
                NullValueHandling = NullValueHandling.Ignore
            };
            string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/intents/{1}?intentView=1", projectId, intentId);

            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString)
            };
            HttpResponseMessage httpResponseMessage = await GetAsync(httpRequestMessage, key);
            //httpResponseMessage.EnsureSuccessStatusCode();

            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return JsonConvert.DeserializeObject<Google.Cloud.Dialogflow.V2.Intent>(strResult, settings);
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        public async Task<SearchIntents> GetIntentList(string key, string projectId, int pageSize = 100, string pageToken = "")
        {
            if (Debug)
            {
                string json = Utils.GetResourceContent(this.GetType(), "DialogFlow.Json.projects_agent_intents_list.json").Substring(1);

                return JsonConvert.DeserializeObject<SearchIntents>(json, new MatchModeStringEnumConverter());
            }
            else
            {
                var settings = new JsonSerializerSettings
                {
                    ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
                    NullValueHandling = NullValueHandling.Ignore
                };
                string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/intents?intentView=1&pageSize={1}&pageToken={2}", projectId, pageSize, pageToken);

                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString)
                };
                HttpResponseMessage httpResponseMessage = await GetAsync(httpRequestMessage, key);
                //httpResponseMessage.EnsureSuccessStatusCode();

                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    return JsonConvert.DeserializeObject<SearchIntents>(strResult, settings);
                }
                Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
                throw new ExceptionWithCode(50044, error.Error.Message);
            }
        }
        public async Task<Operation> BatchDeleteIntents(string key, string projectId, string[] names)
        {
            if (Debug)
            {
                string json = Utils.GetResourceContent(this.GetType(), "DialogFlow.Json.projects_agent_intents_batchDelete.json").Substring(1);

                return JsonConvert.DeserializeObject<Operation>(json, new MatchModeStringEnumConverter());
            }
            else
            {
                var settings = new JsonSerializerSettings
                {
                    ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
                    NullValueHandling = NullValueHandling.Ignore
                };
                string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/intents:batchDelete", projectId);
                StringBuilder intents = new StringBuilder();
                if (names != null && names.Length > 0)
                {
                    intents.Append("[");
                    for (int i = 0; i < names.Length; i++)
                    {
                        intents.Append("{\"name\":\"" + names[i] + "\"}");
                        if (i < names.Length - 1)
                        {
                            intents.Append(",");
                        }
                    }
                    intents.Append("]");
                }

                HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
                {
                    RequestUri = new Uri(uriString),
                    Content = new StringContent("{\"intents\":" + intents.ToString() + "}", Encoding.UTF8, "application/json"),
                };
                //LogHelper.Debugf("BatchDeleteIntents: {0}", "{\"intents\":" + intents.ToString() + "}");
                HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
                //httpResponseMessage.EnsureSuccessStatusCode();

                string strResult = await httpResponseMessage.Content.ReadAsStringAsync();

                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    return JsonConvert.DeserializeObject<Operation>(strResult, settings);
                }
                Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
                throw new ExceptionWithCode(50044, error.Error.Message);
            }
        }
        public async Task<Operation> BatchUpdateIntents(string key, string projectId, Google.Cloud.Dialogflow.V2.Intent[] intents)
        {
#if DEBUG
            Operation debugResult = new Operation();
            debugResult.Done = true;
            debugResult.Error = null;
            debugResult.Name = string.Format("projects/{0}/operation/{1}", projectId, Guid.NewGuid().ToString());
            return debugResult;
#endif
            PropertyIgnoreSerializerContractResolver jsonResolver = new PropertyIgnoreSerializerContractResolver();
            jsonResolver.IgnoreProperty(typeof(Google.Cloud.Dialogflow.V2.Intent), "intentName");
            jsonResolver.IgnoreProperty(typeof(EntityType), "entityTypeName");

            var settings = new JsonSerializerSettings
            {
                ContractResolver = jsonResolver,
                NullValueHandling = NullValueHandling.Ignore
            };
            string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/intents:batchUpdate", projectId);

            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
                Content = new StringContent("{\"intentBatchInline\": {\"intents\":" + JsonConvert.SerializeObject(intents, settings) + "}}", Encoding.UTF8, "application/json"),
            };
            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
            //httpResponseMessage.EnsureSuccessStatusCode();

            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return JsonConvert.DeserializeObject<Operation>(strResult, settings);
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }

        public async Task<Operation> BatchUpdateEntities(string key, string projectId, EntityType[] entities)
        {
#if DEBUG
            Operation debugResult = new Operation();
            debugResult.Done = true;
            debugResult.Error = null;
            debugResult.Name = string.Format("projects/{0}/operation/{1}", projectId, Guid.NewGuid().ToString());
            return debugResult;
#endif
            PropertyIgnoreSerializerContractResolver jsonResolver = new PropertyIgnoreSerializerContractResolver();
            jsonResolver.IgnoreProperty(typeof(Google.Cloud.Dialogflow.V2.Intent), "intentName");
            jsonResolver.IgnoreProperty(typeof(EntityType), "entityTypeName");

            var settings = new JsonSerializerSettings
            {
                ContractResolver = jsonResolver,
                NullValueHandling = NullValueHandling.Ignore
            };
            string uriString = string.Format("https://dialogflow.googleapis.com/v2/projects/{0}/agent/entityTypes:batchUpdate", projectId);

            HttpRequestMessage httpRequestMessage = new HttpRequestMessage()
            {
                RequestUri = new Uri(uriString),
                Content = new StringContent("{\"entityTypeBatchInline\": {\"entityTypes\":" + JsonConvert.SerializeObject(entities, settings) + "}}", Encoding.UTF8, "application/json"),
            };
            //LogHelper.Debug("{\"entityTypeBatchInline\": {\"entityTypes\":" + JsonConvert.SerializeObject(entities, settings) + "}}");
            HttpResponseMessage httpResponseMessage = await PostAsync(httpRequestMessage, key);
            //httpResponseMessage.EnsureSuccessStatusCode();

            string strResult = await httpResponseMessage.Content.ReadAsStringAsync();
            if (httpResponseMessage.IsSuccessStatusCode)
            {
                return JsonConvert.DeserializeObject<Operation>(strResult, settings);
            }
            Operation error = JsonConvert.DeserializeObject<Operation>(strResult);
            throw new ExceptionWithCode(50044, error.Error.Message);
        }
        #endregion
    }
}
